Skip to main content

Utilisation de l'interface de script Git

CODESYS Git fournit une interface de script pour Git. Des exemples d'utilisation de l'interface sont présentés ci-dessous. Vous trouverez également ci-dessous des informations sur la sortie textuelle des messages générés par de nombreuses opérations Git

Pour plus d'informations, voir : Documentation de l'API du moteur de script

Exigences

Pour exécuter les exemples ci-dessous, les éléments suivants sont requis :

  • CODESYS 3.5.19.30 ou supérieur

Les composants suivants sont également requis :

  • CODESYS Library Documentation Support (pour créer la bibliothèque compilée)

  • CODESYS Git 1.6.0.0 ou version ultérieure

  • Une installation Git locale

Important

Utilisez des mots de passe SecureString dans la mesure du possible

Pour une sécurité accrue, les mots de passe doivent être transmis sous forme de .NET SecureString.

Les opérations GIT concernées sont les suivantes : clone, fetch, pull, push

SecureStrings peut être créé dans IronPython comme suit. Le « mot de passe » lui-même doit provenir d'une chaîne sécurisée et non, comme ici à des fins de démonstration, être en texte brut dans le script. En interne, chaque mot de passe fourni est géré de manière sécurisée

        from System.Security import SecureString 

        sec_str_password = SecureString()
        for c in "Passwort":    
            sec_str_password.AppendChar(c)

Pour des mesures de sécurité supplémentaires lors de l'utilisation CODESYS Git voir : Sécurité pour CODESYS Git

Préparation

CODESYS bibliothèque

Parce que non CODESYS les bibliothèques sont actuellement gérées dans Git, les sources d'un CODESYS une bibliothèque est requise. String Functions.library bibliothèque de CODESYS String Libraries le produit est utilisé dans les exemples.

Dépôt Git distant

Pour cet exemple, un référentiel Git nu dans le système de fichiers est utilisé comme référentiel distant.

Pour vous préparer, supprimez d’abord le répertoire correspondant puis créez-en un nouveau.

import shutil
import os 

def prepare_empty_dir(empty_dir_path):
    print("Prepare empty directory at", empty_dir_path)
    shutil.rmtree(empty_dir_path, ignore_errors=True)
    if not(os.path.exists(empty_dir_path) and os.path.isdir(empty_dir_path)):
        os.makedirs(empty_dir_path)

Un dépôt Git vide est ensuite créé.

import subprocess
def create_bare_git_repository(bare_repository_path):
    print("Create bare git repository at", bare_repository_path)
    create_bare_repository_cmd = 'cmd /c "git -C \"' + bare_repository_path + '\" init --bare"'
    try:
        retcode = subprocess.call(create_bare_repository_cmd, shell=True)
        if retcode < 0:
            raise Exception("Creating bare git repository at " + bare_repository_path + " failed: ", -retcode)
        else:
            print("Creating bare git repository at " + bare_repository_path + " succeeded.")
    except Exception as e:
        print("[ERROR] Creating bare git repository failed: ", e)
        raise

Le dépôt Git vide est rempli avec le contenu du CODESYS bibliothèque.

def initialize_bare_git_repository(library_path, local_repository_path, bare_repository_path):
    print("Open library:", library_path)
    project = projects.open(library_path)
     
    print("Initiate local git repository")
    project.git.init(local_repository_path)
    project.git.commit_complete("Create git repo for lib", "user", "mail@mail")
     
    print("Push to remote git repository")
    origin_remote = project.git.remote_add("origin", bare_repository_path)
    project.git.branch_set_upstream_to(origin_remote)
    project.git.push()
    project.git.de_init(cleanUpFileSystem=True)
    project.close()

Le script suivant exécute les fonctions décrites.

import os

def main():
    if projects.primary:
        projects.primary.close()

    basepath = "C:\\CODESYS_Projects\\Git_Scripting_Tutorial\\"

    project_basepath = os.path.join(basepath, "projects\\")
    library_file_name = "ExampleLib1.library"
    library_path = os.path.join(project_basepath, library_file_name)

    remote_repo_basepath = os.path.join(basepath, "remotes\\")
    remote_repo_directory_name = "ExampleLib1RemoteRepo"
    remote_repo_path = os.path.join(remote_repo_basepath, remote_repo_directory_name)

    local_repo_basepath = os.path.join(basepath, "repos\\")
    local_repo_directory_name = "ExampleLib1LocalRepo"
    local_repo_path = os.path.join(local_repo_basepath, local_repo_directory_name)

    print("Create and push library to remote git repository")
    
    prepare_empty_dir(remote_repo_path)
    create_bare_git_repository(remote_repo_path)
    initialize_bare_git_repository(library_path, local_repo_path, remote_repo_path)

    print("[Success] All done")


if __name__ == '__main__':
    main()

Le référentiel Git nu ainsi créé et fourni avec son contenu est utilisé pour les autres exemples.

Clonage d'un dépôt Git distant

La fonction suivante exécute git clone pour un dépôt Git distant.

def clone_git_repository(project_basepath, project_file_name, remote_repo_url_or_path, local_repo_path):
    update_flags = VersionUpdateFlags.UpdateAll | VersionUpdateFlags.SilentMode    
    project = git.clone(project_basepath, project_file_name, remote_repo_url_or_path, local_repo_path, update_flags=update_flags)
    project.save()
    return project

Créer et fusionner une nouvelle branche

La fonction auxiliaire suivante crée de nouveaux objets dans un CODESYS projet à titre d'exemple.

def add_dut(project):
    ST_STRUCT_STR = """\
        a : BOOL;
        b : BIT;
        c : BIT;
    """

    ST_UNION_STR = """\
    TYPE ExampleUnion :
    UNION
        Zahl : INT;
        Prozent : ExampleAlias;
        Bits : ExampleStruct;
    END_UNION
    END_TYPE
    """

   # Create a struct DUT and insert the list of variables just into the right
   # place in line two, row 0 (line numbering starts with line 0)
   example_dut_struct = project.create_dut('ExampleStruct') # DutType.Structure is the default
   example_dut_struct.textual_declaration.insert(2, 0, ST_STRUCT_STR) 

   # Alias types get their "content" via the base type, which will just end up 
   # as one line in the declaration part:    
   # TYPE MyAlias : INT (0..100); END_TYPE 
   example_dut_alias = project.create_dut('ExampleAlias', DutType.Alias, "INT (0..100)") 

   # Instead of injecting the variables into the existing declaration, 
   # one can also just replace the complete declaration part, including the 
   # boilerplate code.
   example_dut_union = project.create_dut('ExampleUnion', DutType.Union)
   example_dut_union.textual_declaration.replace(ST_UNION_STR)

La fonction auxiliaire suivante incrémente la version de build dans les informations de projet d'un CODESYS projet.

def increment_build_version(project):
    """
    Increment build version in project info.
    """
    info = project.get_project_info()
    old_version = info.version
    info.version = (old_version.Major, old_version.Minor, old_version.Build + 1, 0)
    project.save()

La fonction suivante crée d'abord une nouvelle branche et apporte des modifications à cette branche, puis fusionne ces modifications dans la branche principale.

def copy_branch_and_merge(project):
    current_branch = project.git.branch_show_current()
    print("Current branch: ", current_branch.friendly_name)
    project, current_branch = project.git.branch_copy(current_branch, "new_branch", checkout=True)
    print("Current branch: ", current_branch.friendly_name)

    add_dut(project)
    project.git.commit_complete("Added DUT", "user", "mail@mail")

    increment_build_version(project)
    project.git.commit_complete("Incremented build version", "user", "mail@mail")

    project, current_branch = project.git.checkout("master")
    print("Current branch: ", current_branch.friendly_name)
    project, merge_result = project.git.merge("new_branch")
    print("Merged: ", merge_result.ToString())
    project.save()
    return project

Le script suivant s'exécute git clone pour un dépôt Git distant, apporte des modifications au projet, puis transmet les modifications au référentiel Git distant (CopyBranchAndMerge.py).

def main():
    if projects.primary: 
       projects.primary.close()

    basepath = "C:\\CODESYS_Projects\\Git_Scripting_Tutorial\\"

    project_basepath = os.path.join(basepath, "projects\\")
    library_file_name = "ExampleLib1Cloned.library"

    remote_repo_basepath = os.path.join(basepath, "remotes\\")
    remote_repo_directory_name = "ExampleLib1RemoteRepo"
    remote_repo_path = os.path.join(remote_repo_basepath, remote_repo_directory_name)

    local_repo_basepath = os.path.join(basepath, "repos\\")
    local_repo_directory_name = "ExampleLib1LocalRepo"
    local_repo_path = os.path.join(local_repo_basepath, local_repo_directory_name)

    print("Clone project")
    project = clone_git_repository(project_basepath, library_file_name, remote_repo_path, local_repo_path)
    project = copy_branch_and_merge(project)
    project.git.push()
    project.save()
    project.git.de_init(cleanUpFileSystem=True)
    project.save()
    project.close()
    print("[Success] All done")

if __name__ == '__main__':
    main())

Création d'une bibliothèque compilée

Le script suivant s'exécute git clone pour un CODESYS bibliothèque source à partir d'un référentiel Git distant, puis crée une bibliothèque compilée à partir de celui-ci (CreateCompiledLibrary.py).

import os

class CompileError(Exception):
    pass

def clone_git_repository(project_basepath, project_file_name, remote_repo_url_or_path, local_repo_path):
    update_flags = VersionUpdateFlags.UpdateAll | VersionUpdateFlags.SilentMode
    project = git.clone(project_basepath, project_file_name, remote_repo_url_or_path, local_repo_path, update_flags=update_flags)
    project.save()
    return project

def create_compiled_library(project):
    # requires the CODESYS Library Documentation Support Package!
    project.check_all_pool_objects()
    compile_result_message = system.get_messages(category='{97F48D64-A2A3-4856-B640-75C046E37EA9}')[-1]
    if "0 errors" in compile_result_message:
        project.save_as_compiled_library(destination_name=None)
    else:
        raise CompileError("Compile failed: " + compile_result_message)
    return project

basepath = "D:\\JiraTickets\\GIT-145\\"

project_basepath = os.path.join(basepath, "projects\\")

remote_repo_basepath = os.path.join(basepath, "remotes\\")
remote_repo_directory_name = "StringFunctions.git"
remote_repo_path = os.path.join(remote_repo_basepath, remote_repo_directory_name)

local_repo_basepath = os.path.join(basepath, "repos\\")
local_repo_path = os.path.join(local_repo_basepath, "StringFunctions.git")

print("Clone project")
project = clone_git_repository(project_basepath, "String Functions Cloned.library", remote_repo_path, local_repo_path)
project = create_compiled_library(project)
project.git.de_init(cleanUpFileSystem=True)
project.close()

print("[Success] All done")

Installer une bibliothèque à partir d'un référentiel Git distant

Le script suivant s'exécute git clone pour un CODESYS bibliothèque source à partir d'un référentiel Git distant et installe cette bibliothèque dans le CODESYS exemple (InstallLibrary.py).

import os

def clone_git_repository(project_directory_path, project_file_name, remote_repo_url_or_path, local_repo_path):
    update_flags = VersionUpdateFlags.UpdateAll | VersionUpdateFlags.SilentMode
    project = git.clone(project_directory_path, project_file_name, remote_repo_url_or_path, local_repo_path, update_flags=update_flags)
    project.save()
    return project

def install_library(project):
    library_repo = librarymanager.repositories[0]
    librarymanager.install_library(project.path, library_repo, True)

def main():
    if projects.primary:
        projects.primary.close()

     basepath = "C:\\CODESYS_Projects\\Git_Scripting_Tutorial\\"

    project_basepath = os.path.join(basepath, "projects\\")
    library_file_name = "ExampleLib1Cloned2.library"

    remote_repo_basepath = os.path.join(basepath, "remotes\\")
    remote_repo_directory_name = "ExampleLib1RemoteRepo"
    remote_repo_path = os.path.join(remote_repo_basepath, remote_repo_directory_name)

    local_repo_basepath = os.path.join(basepath, "repos\\")
    local_repo_directory_name = "ExampleLib1LocalRepo"
    local_repo_path = os.path.join(local_repo_basepath, local_repo_directory_name)

    print("Clone project")
    project = clone_git_repository(project_basepath, library_file_name, remote_repo_path, local_repo_path)

    print("Install library")
    install_library(project)
    project.git.de_init(cleanUpFileSystem=True)
    project.close()

    print("[Success] All done")

if __name__ == '__main__':
    main()

Sortie de message pour les opérations Git

Lors de l'utilisation CODESYS Git, la plupart des commandes fournissent une sortie basée sur du texte. Lors de la course CODESYS dans la ligne de commande, cette sortie est automatiquement générée lors de l'exécution de CODESYS Git commandes via le pilote de script. Lors de l'utilisation CODESYS Git dans CODESYS Development System, les résultats apparaissent également dans la fenêtre de message.

Structure of the messages: Git:<severity>: [<time>] <text>

In the user interface of CODESYS Git, the output is reduced to: [<time>] <text>

  • severity: catégorie de message. Les catégories vont de l'erreur purement informative à l'erreur critique

  • time: Heure exacte du message. Format : HH:MM:SS

  • text: Contenu du message. Pour les commandes Git standard, le contenu correspond à la commande de ligne de commande qui fournirait le même résultat que l'appel du pilote de script effectué. CODESYS Git commandes qui ne correspondent pas à une commande Git standard (par exemple, Restaurer le projet à partir du référentiel), le texte du message explique l'action effectuée.

Commands with multiple messages:

Pour certaines commandes (par exemple, git log), la sortie est divisée en plusieurs messages. Dans le cas de git log, chaque validation affichée est affichée dans un message distinct. Dans ce cas, afin de préciser que ces messages font partie du git log commande, une référence est faite à la commande d'origine dans les messages.